package com.gomcarter.frameworks.base.config;

import com.gomcarter.frameworks.base.converter.enums.RequestParamToEnumConverterFactory;
import com.gomcarter.frameworks.base.converter.jackson.CustomMappingJacksonConverter;
import com.google.common.base.Strings;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.List;

public class BaseMvcConfigurer implements WebMvcConfigurer {
    private final BaseConfProperties baseConfProperties;
    private final CustomMappingJacksonConverter customMappingJacksonConverter;

    public BaseMvcConfigurer(BaseConfProperties baseConfProperties) {
        this.baseConfProperties = baseConfProperties;
        this.customMappingJacksonConverter = new CustomMappingJacksonConverter(baseConfProperties);
    }

    public BaseMvcConfigurer(BaseConfProperties baseConfProperties,
                             CustomMappingJacksonConverter customMappingJacksonConverter) {
        this.baseConfProperties = baseConfProperties;
        this.customMappingJacksonConverter = customMappingJacksonConverter == null
                ? new CustomMappingJacksonConverter(baseConfProperties)
                : customMappingJacksonConverter;
    }

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        String indexLocation = baseConfProperties.getIndexLocation();
        if (Strings.isNullOrEmpty(indexLocation)) {
            indexLocation = BaseConfConst.ROOT_PATH + BaseConfConst.BASE_INDEX_HTML;
        }
        if (!indexLocation.startsWith(BaseConfConst.ROOT_PATH)) {
            indexLocation = BaseConfConst.ROOT_PATH + indexLocation;
        }
        registry.addViewController(BaseConfConst.ROOT_PATH).setViewName(indexLocation);
    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        Iterator<HttpMessageConverter<?>> iterator = converters.iterator();
        while (iterator.hasNext()) {
            HttpMessageConverter<?> messageConverter = iterator.next();
            if (messageConverter instanceof StringHttpMessageConverter) {
                Charset charset = ((StringHttpMessageConverter) messageConverter).getDefaultCharset();
                if (!Charset.defaultCharset().equals(charset)) {
                    iterator.remove();
                }
            }
            if (messageConverter instanceof MappingJackson2HttpMessageConverter) {
                iterator.remove();
            }
        }
        converters.add(0, customMappingJacksonConverter);
    }

    @Override
    public void addFormatters(FormatterRegistry registry) {
        if (baseConfProperties.isEnableEnumResolver()) {
            registry.addConverterFactory(new RequestParamToEnumConverterFactory(baseConfProperties.getEnumResolverMethodName()));
        }
    }
}
